#ifndef RENDEROBJECT_H
#define RENDEROBJECT_H

#include <global.h>
#include <string>
#include <vector>

namespace NITK {
class Image;
class RenderObjectLayout;
class RenderObject;
class RenderObjectData {
public:
    virtual ~RenderObjectData();
    RenderObjectData(RenderObject *object, int t)
        : renderObject(object), layout(0), type(t), image(0),
          zValue(0), background(0), foreground(0), alignment(0) {}

    RenderObject *renderObject;
    RenderObjectLayout *layout;
    const int type;
    Image *image;
    double zValue;
    Rectangle geometry;
    unsigned int background, foreground;
    std::string text;
    unsigned int alignment;
    bool deleteOverride;
};

class RenderObject
{
public:
    enum Type { Type_Normal, Type_Card, Type_CardSpot, Type_Layout, Type_Spacer };
    RenderObject(Type type, unsigned int background = 0);
    RenderObject(Type type, Image *image);
    RenderObject(Type type, int r, int g, int b, int a = 255);
    RenderObject(Type type, const std::string &pathToImage);
    virtual ~RenderObject();

    Type type() const;
    bool setBackground(const std::string &path); // maybe image sequences?
    void setBackground(Image *image);
    void setBackground(unsigned int color);
    inline void setBackground(int r, int g, int b, int a = 255) { setBackground(Color::rgba(r, g, b, a)); }
    unsigned int background() const;
    void setForeground(unsigned int color);
    inline void setForeground(int r, int g, int b, int a = 255) { setForeground(Color::rgba(r, g, b, a)); }
    unsigned int foreground() const;
    double zValue() const;
    void setZValue(double z);
    Rectangle geometry() const;
    virtual void setGeometry(const Rectangle &rectangle);
    void update();
    Image *image() const;
    void setText(const std::string &string);
    std::string text() const;

    enum Alignment {
        AlignCenter = 0x0,
        AlignLeft = 0x1,
        AlignRight = 0x2,
        AlignTop = 0x4,
        AlignBottom = 0x8
    };
    unsigned int alignment() const;
    void setAlignment(unsigned int align);
protected:
    UNIMPLEMENTED void init(RenderObject *, int type);
    UNIMPLEMENTED void geometryChanged();
    friend class Platform;
    friend class ApplicationEngine;
    RenderObjectData *data;
};

class RenderObjectLayout : public RenderObject
{
public:
    enum LayoutType { VerticalBox, HorizontalBox /*Flow, Grid */ };
    RenderObjectLayout(LayoutType type);
    ~RenderObjectLayout();
    LayoutType layoutType() const;
    const std::vector<RenderObject*> &renderObjects() const;
    int count() const;
    RenderObject *renderObjectAt(int index) const;
    RenderObject *takeAt(int index);
    bool removeRenderObject(RenderObject *renderObject);
    void insertRenderObject(int index, RenderObject *object);
    inline void addRenderObject(RenderObject *object) { insertRenderObject(-1, object); }
    inline void addSpacer() { addRenderObject(new RenderObject(Type_Spacer)); }
    virtual void setGeometry(const Rectangle &rect);
    double spacing() const;
    void setSpacing(double val);
    Size minimumSize() const;
private:
    struct Data {
        Data(LayoutType type) : layoutType(type), spacing(2) {}
        const LayoutType layoutType;
        double spacing;
        std::vector<RenderObject*> renderObjects;
        mutable Size minimumSize;
    } data;
};

};

#endif
